package org.venus.onvif.util;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import okhttp3.*;
import okhttp3.logging.HttpLoggingInterceptor;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.venus.onvif.config.Config;

import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Component
public class VideoUtils {

    private final static Logger logger = LoggerFactory.getLogger(VideoUtils.class);

    private OkHttpClient client;

    public interface RequestCallback {
        void run(JSONObject response);
    }


    public JSONObject closeStreams(String app, String stream) {
        Map<String, Object> param = new HashMap<>();
        param.put("vhost", "__defaultVhost__");
        param.put("app", app);
        param.put("stream", stream);
        param.put("force", 1);
        return sendPost("close_streams", param, null);
    }


    public JSONObject addStreamProxy(String app, String stream, String url) {
        Map<String, Object> param = new HashMap<>();
        param.put("vhost", "__defaultVhost__");
        param.put("app", app);
        param.put("stream", stream);
        param.put("url", url);
        return sendPost("addStreamProxy", param, null);
    }


    public JSONObject getMediaList(String app, String stream, String url) {
        Map<String, Object> param = new HashMap<>();
        param.put("vhost", "__defaultVhost__");
        param.put("app", app);
        param.put("stream", stream);
        return sendPost("getMediaList", param, null);
    }

    private OkHttpClient getClient() {
        if (client == null) {
            OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
            //todo 暂时写死超时时间 均为5s
            // 设置连接超时时间
            httpClientBuilder.connectTimeout(5, TimeUnit.SECONDS);
            // 设置读取超时时间
            httpClientBuilder.readTimeout(10, TimeUnit.SECONDS);
            // 设置连接池
            httpClientBuilder.connectionPool(new ConnectionPool(16, 5, TimeUnit.MINUTES));
            if (logger.isDebugEnabled()) {
                HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> {
                    logger.debug("http请求参数：" + message);
                });
                logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
                // OkHttp進行添加攔截器loggingInterceptor
                httpClientBuilder.addInterceptor(logging);
            }
            client = httpClientBuilder.build();
        }
        return client;

    }

    public JSONObject sendPost(String api, Map<String, Object> param, RequestCallback callback) {
        OkHttpClient client = getClient();
        String url = String.format("http://%s:%s/index/api/%s", Config.mediaServer.ip, Config.mediaServer.port, api);
        System.out.println("流媒体地址:" + url);
        JSONObject responseJSON = new JSONObject();
        //-2自定义流媒体 调用错误码
        responseJSON.put("code", -2);
        responseJSON.put("msg", "流媒体调用失败");

        FormBody.Builder builder = new FormBody.Builder();
        builder.add("secret", Config.mediaServer.secret);
        if (param != null && param.keySet().size() > 0) {
            for (String key : param.keySet()) {
                if (param.get(key) != null) {
                    builder.add(key, param.get(key).toString());
                }
            }
        }

        FormBody body = builder.build();

        Request request = new Request.Builder()
                .post(body)
                .url(url)
                .build();
        if (callback == null) {
            try {
                Response response = client.newCall(request).execute();
                if (response.isSuccessful()) {
                    ResponseBody responseBody = response.body();
                    if (responseBody != null) {
                        String responseStr = responseBody.string();
                        responseJSON = JSON.parseObject(responseStr);
                    }
                } else {
                    response.close();
                    Objects.requireNonNull(response.body()).close();
                }
            } catch (IOException e) {
                logger.error(String.format("[ %s ]请求失败: %s", url, e.getMessage()));

                if (e instanceof SocketTimeoutException) {
                    //读取超时超时异常
                    logger.error(String.format("读取流媒体数据失败: %s, %s", url, e.getMessage()));
                }
                if (e instanceof ConnectException) {
                    //判断连接异常，我这里是报Failed to connect to 10.7.5.144
                    logger.error(String.format("连接流媒体失败: %s, %s", url, e.getMessage()));
                }

            } catch (Exception e) {
                logger.error(String.format("访问流媒体失败: %s, %s", url, e.getMessage()));
            }
        } else {
            client.newCall(request).enqueue(new Callback() {

                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) {
                    if (response.isSuccessful()) {
                        try {
                            String responseStr = Objects.requireNonNull(response.body()).string();
                            callback.run(JSON.parseObject(responseStr));
                        } catch (IOException e) {
                            logger.error(String.format("[ %s ]请求失败: %s", url, e.getMessage()));
                        }

                    } else {
                        response.close();
                        Objects.requireNonNull(response.body()).close();
                    }
                }

                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {
                    logger.error(String.format("连接流媒体失败: %s, %s", call.request().toString(), e.getMessage()));

                    if (e instanceof SocketTimeoutException) {
                        //读取超时超时异常
                        logger.error(String.format("读取流媒体数据失败: %s, %s", call.request().toString(), e.getMessage()));
                    }
                    if (e instanceof ConnectException) {
                        //判断连接异常，我这里是报Failed to connect to 10.7.5.144
                        logger.error(String.format("连接流媒体失败: %s, %s", call.request().toString(), e.getMessage()));
                    }
                }
            });
        }


        return responseJSON;
    }
}
